/** @class */
function extension(project) {
	this.project = project;
	this.whiteList = {
		opcode: [],
		extension: []
	}
}

/** @menber */
extension.prototype.remove = function () {
	let that = this;
	foreach(that.project.targets, function (target) {
		foreach(target.blocks, function (block, i) {
			if (!Array.isArray(block)) {
				if (!that.whiteList.opcode.includes(block.opcode)) {
					//console.log(block.opcode);
					//console.log(i);
					//console.log(block.next);
					let nx = block.next;
					removeBlock(target.blocks, i);
					foreach(target.blocks, function (block) {
						replaceBlock(block, i, nx);
					});
					//replaceBlockWithCustom(target.block, i, block.opcode);
				}
			}
		})
	});
	foreach(that.project.monitors, function (monitor, i) {
		//if(!monitor.visible){
		//	delete that.project.monitors[i];
		//}
		if (!that.whiteList.opcode.includes(monitor.opcode)) {
			delete that.project.monitors[i];
		}
	});
	for (let i = 0; i < that.project.extensions.length; i++) {
		if (!that.whiteList.extension.includes(that.project.extensions[i])) {
			that.project.extensions.splice(i, 1);
			i--;
		}
	}
};

/** @menber */
extension.prototype.getWhiteList = function () {
	let that = this;
	foreach(that.project.targets, function (target) {
		foreach(target.blocks, function (block) {
			if (!Array.isArray(block)) {
				if (!that.whiteList.opcode.includes(block.opcode)) {
					that.whiteList.opcode.push(block.opcode);
				}
			}
		})
	});
	foreach(that.project.monitors, function (monitor) {
		//if(!monitor.visible){
		//	delete that.project.monitors[i];
		//}
		if (!that.whiteList.opcode.includes(monitor.opcode)) {
			that.whiteList.opcode.push(monitor.opcode);
		}
	});
	for (let i = 0; i < that.project.extensions.length; i++) {
		if (!that.whiteList.extension.includes(that.project.extensions[i])) {
			that.whiteList.extension.push(that.project.extensions[i]);
			i--;
		}
	}
};

function replaceBlock(block, old, New) {
	if (block.parent === old) {
		block.parent = New;
	}
	if (block.next === old) {
		block.next = New;
	}
	foreach(block.inputs, function (input) {
		switch (input[0]) {
			case 3:
				if (input[2] === old) {
					input[2] = New;
				}
				/* fall through */
				case 1:
				case 2:
					if (input[1] === old) {
						input[1] = New;
					}
		}
	});
}

function removeBlock(blocks, id) {
	foreach(blocks[id].inputs, function (input) {
		switch (input[0]) {
			case 3:
				if (typeof input[2] === "string") {
					removeBlock(blocks, input[2]);
				}
				/* fall through */
				case 1:
				case 2:
					if (typeof input[1] === "string") {
						removeBlock(blocks, input[1]);
					}
		}
	})
	delete blocks[id];
}

function foreach(object, callback) {
	for (let i in object) {
		callback(object[i], i);
	}
}
